﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YJKGeometryFuncs;

namespace YJKRevitDimension.ArrowDimension
{
	public class ArrowDimTempFamily
	{
		public static void OpenFamilyDocument(UIDocument m_UIdoc, string familyName, ref Document newDoc, bool ifNeedTrans = true)
		{
			if (ifNeedTrans)
			{
				try
				{
					string text = ArrowDimTempFamily.FamilyName(m_UIdoc, familyName + ".rfa");
					newDoc = m_UIdoc.Document.Application.OpenDocumentFile(text);
					return;
				}
				catch (Exception)
				{
					return;
				}
			}
			string text2 = ArrowDimTempFamily.FamilyName(m_UIdoc, familyName + ".rfa");
			newDoc = m_UIdoc.Document.Application.OpenDocumentFile(text2);
		}

		public static string FamilyName(UIDocument m_UIdoc, string strFileName)
		{
			string appRootPath = AssistFunc.GetAppRootPath();
			string versionNumber = m_UIdoc.Application.Application.VersionNumber;
			return string.Concat(new string[]
			{
				appRootPath,
				"\\FamilyLib\\Family\\",
				versionNumber,
				"\\ArrowDimension\\",
				strFileName
			});
		}

		public static void Draw(UIDocument m_UIdoc, Autodesk.Revit.DB.Document newDoc, ArrowDimData data, List<XYZ> lstPickPoint, out string strPath, bool ifNeedTrans = true, ViewPlan inputView = null)
		{
			ArrowDimTempFamily.OpenFamilyDocument(m_UIdoc, data.StrArrowType, ref newDoc, ifNeedTrans);
			ArrowDimTempFamily.DrawLine(m_UIdoc, newDoc, data, lstPickPoint, out ArrowDimTempFamily.LstDetailCurve, ifNeedTrans, inputView);
			ArrowDimArrow.FindAndModifyArrow(m_UIdoc, newDoc, data, lstPickPoint, true);
			if (data.StrAlignStyle.Equals("在线端"))
			{
				ArrowDimText.FindAndModifyText(m_UIdoc, newDoc, data, lstPickPoint, ArrowDimTempFamily.LstDetailCurve, Convert.ToInt32(ArrowDimTempFamily.UpOrDown.Up));
			}
			else if (data.StrAlignStyle.Equals("齐线端"))
			{
				ArrowDimText.FindAndModifyText(m_UIdoc, newDoc, data, lstPickPoint, ArrowDimTempFamily.LstDetailCurve, Convert.ToInt32(ArrowDimTempFamily.UpOrDown.Up));
				ArrowDimText.FindAndModifyText(m_UIdoc, newDoc, data, lstPickPoint, ArrowDimTempFamily.LstDetailCurve, Convert.ToInt32(ArrowDimTempFamily.UpOrDown.Down));
			}
			else
			{
				ArrowDimText.FindAndModifyText(m_UIdoc, newDoc, data, lstPickPoint, ArrowDimTempFamily.LstDetailCurve, Convert.ToInt32(ArrowDimTempFamily.UpOrDown.Up));
				ArrowDimText.FindAndModifyText(m_UIdoc, newDoc, data, lstPickPoint, ArrowDimTempFamily.LstDetailCurve, Convert.ToInt32(ArrowDimTempFamily.UpOrDown.Down));
			}
			int arrowFamilyNum = ArrowDimTempFamily.GetArrowFamilyNum(m_UIdoc);
			ArrowDimTempFamily.SaveTempFamily(newDoc, arrowFamilyNum, out strPath);
			Family family;
			ArrowDimTempFamily.LoadFamily(m_UIdoc.Document, strPath, out family, ifNeedTrans);
			ArrowDimTempFamily.NewFamilyInstance(m_UIdoc.Document, family, lstPickPoint[0], data.StrArrowType, ifNeedTrans, inputView);
			lstPickPoint.Clear();
			if (File.Exists(strPath))
			{
				File.Delete(strPath);
			}
		}

		public static void DrawLine(UIDocument m_UIdoc, Autodesk.Revit.DB.Document newDoc, ArrowDimData data, List<XYZ> lstPickPoint, out List<DetailCurve> LstDetailCurve, bool ifNeedTrans = true, ViewPlan inputView = null)
		{
			LstDetailCurve = new List<DetailCurve>();
			Transform transform = Transform.CreateTranslation(XYZ.Zero);
			Autodesk.Revit.DB.View viewPlan;
			if (inputView == null)
			{
				viewPlan = m_UIdoc.Document.ActiveView;
			}
			else
			{
				viewPlan = inputView;
			}
			Transform aviewTransform = ArrowDimTempFamily.GetAViewTransform(viewPlan);
			double num = (double)m_UIdoc.Document.ActiveView.get_Parameter(BuiltInParameter.VIEW_SCALE).AsInteger();
			transform = transform.ScaleBasis(1.0 / num);
			Transform transform2;
			ArrowDimTempFamily.TryGetUseTransFormForStartPoint(lstPickPoint, aviewTransform, out transform2);
			transform = transform.Multiply(transform2);
			Transaction transaction = new Transaction(newDoc);
			try
			{
				FilteredElementCollector filteredElementCollector = new FilteredElementCollector(newDoc);
				filteredElementCollector.OfClass(typeof(Autodesk.Revit.DB.View));
				CurveArray curveArray = new CurveArray();
				List<XYZ> list = new List<XYZ>();
				list.AddRange(lstPickPoint);
				if (data.StrArrowType == "双侧空心箭头")
				{
					double num2 = AssistFunc.mmToFeet((double)(3 * m_UIdoc.ActiveView.Scale));
					XYZ xyz = lstPickPoint[0];
					XYZ xyz2 = lstPickPoint[1];
					if (!Geometry.LessThan(xyz.DistanceTo(xyz2), num2))
					{
						XYZ xyz3 = (xyz2 - xyz).Normalize();
						xyz += xyz3 * num2;
						list[0] = xyz;
					}
				}
				transaction.Start("ArrowLine");
				for (int i = 0; i < list.Count - 1; i++)
				{
					Curve curve = Line.CreateBound(Geometry.TransformPoint(list[i], aviewTransform), Geometry.TransformPoint(list[i + 1], aviewTransform));
					curveArray.Append(curve.CreateTransformed(transform));
				}
				foreach (object obj in newDoc.FamilyCreate.NewDetailCurveArray(filteredElementCollector.First<Element>() as View, curveArray))
				{
					DetailCurve item = (DetailCurve)obj;
					LstDetailCurve.Add(item);
				}
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

		public static Transform GetAViewTransform(Autodesk.Revit.DB.View viewPlan)
		{
			if (viewPlan is ViewPlan)
			{
				return Transform.CreateTranslation(XYZ.Zero);
			}
			Transform transform = Transform.CreateTranslation(XYZ.Zero);
			transform.BasisX = viewPlan.RightDirection;
			transform.BasisY = viewPlan.UpDirection;
			transform.BasisZ = viewPlan.ViewDirection;
			Transform inverse = transform.Inverse;
			inverse.Origin = XYZ.Zero;
			return inverse;
		}

		private static bool TryGetUseTransFormForStartPoint(List<XYZ> LstPickPoint, Transform inputTransform, out Transform useTransform)
		{
			XYZ point = null;
			useTransform = null;
			if (!ArrowDimTempFamily.TryGetStartPoint(LstPickPoint, out point))
			{
				return false;
			}
			useTransform = Transform.CreateTranslation(XYZ.Zero.Add(-Geometry.TransformPoint(point, inputTransform)));
			return true;
		}

		private static bool TryGetStartPoint(List<XYZ> LstPickPoint, out XYZ startPoint)
		{
			startPoint = null;
			if (LstPickPoint.Count == 0)
			{
				return false;
			}
			startPoint = LstPickPoint[0];
			return true;
		}

		private static int GetArrowFamilyNum(UIDocument uidoc)
		{
			Document document = uidoc.Document;
			string strFamilyNameHead = "盈建科箭头标注";
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(document);
			ElementClassFilter elementClassFilter = new ElementClassFilter(typeof(Family));
			filteredElementCollector.WherePasses(elementClassFilter);
			IEnumerable<Element> enumerable = from e in filteredElementCollector.WherePasses(elementClassFilter).WhereElementIsNotElementType().ToElements() as List<Element>
			where e.Name.Contains(strFamilyNameHead)
			select e;
			if (enumerable == null)
			{
				return 0;
			}
			int num = 0;
			foreach (Element element in enumerable)
			{
				int num2 = 0;
				if (int.TryParse(element.Name.Substring(strFamilyNameHead.Length), out num2) && num2 > num)
				{
					num = num2;
				}
			}
			return num + 1;
		}

		public static bool SaveTempFamily(Autodesk.Revit.DB.Document newDoc, int inum, out string strPath)
		{
			bool result;
			try
			{
				strPath = Environment.GetEnvironmentVariable("TEMP");
				strPath = strPath + "\\盈建科箭头标注" + inum.ToString() + ".rfa";
				if (File.Exists(strPath))
				{
					File.Delete(strPath);
				}
				SaveAsOptions saveAsOptions = new SaveAsOptions();
				saveAsOptions.OverwriteExistingFile = true;
				newDoc.SaveAs(strPath, saveAsOptions);
				newDoc.Close(false);
				result = true;
			}
			catch (Exception)
			{
				strPath = "";
				result = false;
			}
			return result;
		}

		private static void LoadFamily(Autodesk.Revit.DB.Document doc, string strPath, out Family family, bool ifNeedTrans = true)
		{
			if (ifNeedTrans)
			{
				Transaction transaction = new Transaction(doc, "LoadFamily");
				try
				{
					transaction.Start();
                    doc.LoadFamily(strPath, out family);
					if (family == null)
					{
						transaction.RollBack();
					}
					else
					{
						transaction.Commit();
					}
					return;
				}
				catch (Exception)
				{
					family = null;
					transaction.RollBack();
					return;
				}
			}
            doc.LoadFamily(strPath, out family);
		}

		private static void NewFamilyInstance(Autodesk.Revit.DB.Document doc, Family family, XYZ ptLocation, string strType, bool ifNeedTrans = true, ViewPlan inputView = null)
		{
			if (ifNeedTrans)
			{
				using (Transaction transaction = new Transaction(doc, "CreateNewFamily"))
				{
					try
					{
						transaction.Start();
						ArrowDimTempFamily.CreatFamilyInstanceMethod(doc, family, ptLocation, strType, inputView);
						transaction.Commit();
						return;
					}
					catch (Exception)
					{
						transaction.RollBack();
						return;
					}
				}
			}
			ArrowDimTempFamily.CreatFamilyInstanceMethod(doc, family, ptLocation, strType, inputView);
		}

		private static void CreatFamilyInstanceMethod(Autodesk.Revit.DB.Document doc, Family family, XYZ ptLocation, string strType, ViewPlan inputView = null)
		{
			FamilySymbol familySymbol = null;
			foreach (FamilySymbol familySymbol2 in family.GetSymbols())
			{
				if (familySymbol2.Name == strType)
				{
					familySymbol = familySymbol2;
					break;
				}
			}
			if (!familySymbol.IsActive)
			{
				familySymbol.Activate();
			}
			FamilyInstance familyInstance;
			if (inputView != null)
			{
				familyInstance = doc.Create.NewFamilyInstance(ptLocation, familySymbol, inputView);
			}
			else
			{
				familyInstance = doc.Create.NewFamilyInstance(ptLocation, familySymbol, doc.ActiveView);
			}
			doc.Regenerate();
			if (familyInstance.FacingOrientation.Normalize().Z < 0.0)
			{
				Line line = Line.CreateUnbound((familyInstance.Location as LocationPoint).Point, doc.ActiveView.ViewDirection);
				ElementTransformUtils.RotateElement(doc, familyInstance.Id, line, Math.PI);
			}
		}

		public static List<DetailCurve> LstDetailCurve = new List<DetailCurve>();

		private enum UpOrDown
		{
			Up = 1,
			Down = -1
		}
	}
}
